#define _GNU_SOURCE
#include "daemon_sub_process.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/reboot.h>
#include <signal.h>
#include "log/log.h"

/**
 * 初始子进程结构体
 */
SubProcess *daemon_sub_process_init(char * cmd_param)
{
    SubProcess *sp = (SubProcess *)malloc(sizeof(SubProcess));
    // 初始化sp的属性
    sp->cmd_param = cmd_param;
    sp->pid = -1;
    sp->fail_count = 0;

    return sp;
}

/**
 * 检查启动子进程
 */
int daemon_sub_process_checkStart(SubProcess *sp)
{
    int status =0;
    // 检查
        // 如果子进程正在运行中， 直接结束
        // WNOHANG: 如果子进程正在运行，waitpid()返回0
    if (sp->pid>0 && waitpid(sp->pid, &status, WNOHANG) == 0)
    {
        log_debug("进程(%s)正在运行中，无需启动", sp->cmd_param);
        return 0;
    }

    // pid===-1 => 子进程还没有启动过
    // 子进程启动过，但已经结束了
    if (status!=0)  // 异常结束
    {
        // 让失败次数+1
        sp->fail_count++;
        // 如果失败次数大于最大值，则重启系统
        if (sp->fail_count >MAX_FAIL_COUNT)
        {
            reboot(RB_AUTOBOOT);
        }
    }

    // 启动  (没有启动过/已经结束了)
    // if (sp->pid==-1 || status!=0)
        // 创建子进程
    sp->pid =fork();
        // 在子进程运行程序的指定模块
    if (sp->pid == 0)
    {
        // sp->pid = getpid();
        char *argv[] = {EXE_PATH, sp->cmd_param, NULL};
        execve(EXE_PATH, argv, NULL);
        log_error("找不到对应程序执行，结束当前进程");
        // 找不到对应程序执行，结束当前进程
        _exit(EXIT_FAILURE);
    } else if (sp->pid == -1)
    {
        log_error("创建子进程失败!");
        return -1;
    }

    return 0;

}

/**
 * 停止子进程
 */
int daemon_sub_process_stop(SubProcess *sp)
{
    // 杀死子进程
    kill(sp->pid, SIGTERM);
    // 等待子进程结束
    waitpid(sp->pid, NULL, 0);
    // 释放sp
    free(sp);
}